
cdef extern from "stdio.h":
    pass

cdef extern from "string.h":
    char *strcpy (char *dest, char *src)



ctypedef int size_t

cdef extern from "stdlib.h":
  void *malloc(size_t size)
  int free(void*)
  int sizeof()


cdef extern from "Python.h":
    object PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *))
    void *PyCObject_AsVoidPtr(object o)
    void *PyCObject_GetDesc(object o)


#import coords
#import coords._pytpmmodule
#import ctypes
#aa = ctypes.CDLL(coords._pytpmmodule.__file__)

cimport  c_numpy
#from c_numpy cimport npy_bool
cimport c_python


c_numpy.import_array()
#c_numpy.import_ufunc()

ctypedef int Py_ssize_t


class NotYetImplemented(Exception):
    pass


#cdef extern from "../C/wcs.h":


cdef extern from "pgplot_fake.c":
    pass

cdef extern from "pywcs.h":
    ctypedef struct _wcsprm

    ctypedef extern class pywcs.WCSBase [object PyWcsprm]:
        cdef _wcsprm *x


cdef extern from "wcsgrid_jj.c":
    ctypedef int (*coord_conv_bb)(double , double , double *, double *, void *)
    
    ctypedef struct conv_function_struct:
        coord_conv_bb cf1
        void * cf1_data
        coord_conv_bb cf2
        void * cf2_data
        
    
    int wcsgrid_jj(_wcsprm *wcs, float x1, float y1, float x2, float y2, 
                   char *coord_format,
                   int labctl, int labden,
                   int axis_num, 
                   int ng, double *grid)

    int wcsgrid_gal(_wcsprm *wcs, float x1, float y1, float x2, float y2, 
                    char *coord_format,
                    int labctl, int labden,
                    int axis_num, 
                    int ng, double *grid)

    int wcsgrid_bb(_wcsprm *wcs, float x1, float y1, float x2, float y2, 
                   char *coord_format, int labctl,
                   int labden,
                   int axis_num, 
                   int ng, double *grid,
                   conv_function_struct *cfs)




cdef public void pgnumb_(int *mm_p, int *pp_p, int *form_p, char *string,
                         int* nc_p, int string_length):

    #print mm_p[0], pp_p[0], form_p[0], string, string_length
    
    s_py = pypgnumb(mm_p[0], pp_p[0], form_p[0])

    if string_length <= len(s_py):
        strcpy(string, '*')
        nc_p[0] = 1
    else:
        strcpy(string, s_py)
        nc_p[0] = len(s_py)
        


def pypgnumb(mm, pp, form):

    s = {True:"", False:"-"}[mm>0]
    mms = "%d" % abs(mm)
    if mm == 0:
        return "0"

    if form == 0:
        if 0.01 < abs(mm) * 10**pp < 10000:
            form = 1
        else:
            form = 2
        
    if form == 1 :
        if pp >= 0:
            return s+mms+("0"*pp)
        if pp < 0:
            if len(mms) <= -pp:
                return s+"0."+"0"*(-pp-len(mms)) + mms
            else:
                return s+mms[:pp]+"." + mms[pp:]

    if form == 2 : # exponential
        
        exp1 = len(mms) - 1
        exp2 = exp1+pp

        r = [s, mms[0]]
        if exp1 != 0: r.extend([".", mms[1:]]) 
        if exp2 != 0: r.extend(["^x10^u", str(exp2), "^d"]) 
        
        return "".join(r)




wcsgrid_pgline_linelist = []
wcsgrid_pgptxt_textlist = []


cdef public void wcsgrid_pgline(int n, float *xpts, float *ypts):

    cdef c_numpy.npy_intp dims
    cdef float *xf, *yf
    cdef int i
    
    dims = n
    
    x = c_numpy.PyArray_EMPTY(1, &dims, c_numpy.NPY_FLOAT, 0)
    y = c_numpy.PyArray_EMPTY(1, &dims, c_numpy.NPY_FLOAT, 0)

    xf = <float *> c_numpy.PyArray_DATA(x)
    yf = <float *> c_numpy.PyArray_DATA(y)

    for i from 0 <= i < n:
        xf[i] = xpts[i] - 1.
        yf[i] = ypts[i] - 1.
        
    wcsgrid_pgline_linelist.append((x, y))


cdef public void wcsgrid_pgptxt(float x, float y, float angle, float fjust, char *text):
    wcsgrid_pgptxt_textlist.append((x-1., y-1., angle, fjust, text))


#cdef public int addline(int i):
#    lll.append(i)

def wcsgrid(WCSBase wcsobj, float x1, float y1, float x2, float y2,
            char *coord_format, int labctl, int labden,
            int axis_number_for_grid, grid):
    cdef _wcsprm *wcs
    cdef int ng #1, ng2
    cdef double *g #1, *g2
    
    wcs = wcsobj.x

    ng = len(grid)
    #ng2 = len(grid2)

    g = <double *> malloc(sizeof(double) * (ng + 1))
    g[0] = 0.
    for i from 0 <= i < ng:
        g[i+1] = grid[i]

    #g2 = <double *> malloc(sizeof(double) * (ng2 + 1))
    #g2[0] = 0.
    #for i from 0 <= i < ng2:
    #    g2[i+1] = grid2[i]
            
    
    wcsgrid_jj(wcs,
               x1+1., y1+1., x2+1., y2+1.,
               coord_format, labctl, labden,
               axis_number_for_grid, ng, g)
    #ng1, g1, ng2, g2)

    
    free(g)
    

# def wcsgrid_g(WCSBase wcsobj, float x1, float y1, float x2, float y2,
#               char *coord_format, int labctl, int labden,
#               int axis_number_for_grid, grid):
#     cdef _wcsprm *wcs
#     cdef int ng #1, ng2
#     cdef double *g #1, *g2
    
#     wcs = wcsobj.x

#     ng = len(grid)
#     #ng2 = len(grid2)

#     g = <double *> malloc(sizeof(double) * (ng + 1))
#     g[0] = 0.
#     for i from 0 <= i < ng:
#         g[i+1] = grid[i]

#     #g2 = <double *> malloc(sizeof(double) * (ng2 + 1))
#     #g2[0] = 0.
#     #for i from 0 <= i < ng2:
#     #    g2[i+1] = grid2[i]
            
    
#     wcsgrid_gal(wcs,
#                 x1+1., y1+1., x2+1., y2+1.,
#                 coord_format, labctl, labden,
#                 axis_number_for_grid, ng, g)
#     #ng1, g1, ng2, g2)

    
#     free(g)


# def wcsgrid_bb2(WCSBase wcsobj, float x1, float y1, float x2, float y2,
#                 char *coord_format, int labctl, int labden,
#                 int axis_number_for_grid, grid,
#                 coord_conv_obj):
#     cdef _wcsprm *wcs
#     cdef int ng #1, ng2
#     cdef double *g #1, *g2
#     #cdef (coord_conv_bb *) cc
    
#     wcs = wcsobj.x

#     ng = len(grid)
#     #ng2 = len(grid2)

#     g = <double *> malloc(sizeof(double) * (ng + 1))
#     g[0] = 0.
#     for i from 0 <= i < ng:
#         g[i+1] = grid[i]

#     #g2 = <double *> malloc(sizeof(double) * (ng2 + 1))
#     #g2[0] = 0.
#     #for i from 0 <= i < ng2:
#     #    g2[i+1] = grid2[i]
            
    
#     wcsgrid_bb(wcs,
#                x1+1., y1+1., x2+1., y2+1.,
#                coord_format, labctl, labden,
#                axis_number_for_grid, ng, g,
#                )
#     #ng1, g1, ng2, g2)

    
#     free(g)
    


## TODO create coord_conv.h pxd file
    
cimport c_coord_conv

cimport c_pytpm
#import _pytpm
#c_pytpm.init_pytpm()

#_pytpm.AstroCoordConvFunc

def wcsgrid_coord_conv(WCSBase wcsobj, float x1, float y1, float x2, float y2,
                       char *coord_format, int labctl, int labden,
                       int axis_number_for_grid, grid,
                       c_pytpm.AstroCoordConvFunc cf1,
                       c_pytpm.AstroCoordConvFunc cf2):
#object cf1, object cf2):
    cdef _wcsprm *wcs
    cdef int ng #1, ng2
    cdef double *g #1, *g2
    #cdef (coord_conv_bb *) cc

    #cdef c_coord_conv.coord_conv_struct *ccs1
    #cdef c_coord_conv.coord_conv_struct *ccs2

    cdef conv_function_struct _cfs

    
    #ccs1 = <c_coord_conv.coord_conv_struct *> PyCObject_AsVoidPtr(cf1.get_coord_conv_c_struct())
    #ccs2 = <c_coord_conv.coord_conv_struct *> PyCObject_AsVoidPtr(cf2.get_coord_conv_c_struct())



    #_cfs.cf1 = ccs1.func;
    #_cfs.cf1_data = ccs1.data;
    #_cfs.cf2 = ccs2.func;
    #_cfs.cf2_data = ccs2.data;

    _cfs.cf1 = cf1.c_func
    _cfs.cf1_data = cf1.c_data
    _cfs.cf2 = cf2.c_func
    _cfs.cf2_data = cf2.c_data

    wcs = wcsobj.x

    ng = len(grid)
    #ng2 = len(grid2)

    g = <double *> malloc(sizeof(double) * (ng + 1))
    g[0] = 0.
    for i from 0 <= i < ng:
        g[i+1] = grid[i]

    #g2 = <double *> malloc(sizeof(double) * (ng2 + 1))
    #g2[0] = 0.
    #for i from 0 <= i < ng2:
    #    g2[i+1] = grid2[i]
            
    

    wcsgrid_bb(wcs,
               x1+1., y1+1., x2+1., y2+1.,
               coord_format, labctl, labden,
               axis_number_for_grid, ng, g,
               &_cfs)
    #ng1, g1, ng2, g2)

    
    free(g)
    

